package net.xo68.destiny.manager.config;

import lombok.extern.slf4j.Slf4j;
import net.xo68.destiny.core.lock.DistributedLockInfo;
import net.xo68.destiny.core.lock.DistributedLockStatus;
import net.xo68.destiny.core.lock.DistributedLockStore;
import net.xo68.destiny.core.util.TimeUtils;
import net.xo68.destiny.manager.entity.DistributedLock;
import net.xo68.destiny.manager.service.DistributedLockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 分布式锁，持久化信息存储实现
 * @author wuxie
 * @version 2020-12-17
 */
@Slf4j
@Component
public class DistributedLockStoreImpl implements DistributedLockStore {

    @Autowired
    private DistributedLockService distributedLockService;

    @Override
    public DistributedLockInfo tryLock(String lockKey, String lockHold, long tryTimeoutSecond, long periodSecond) {
        DistributedLockInfo lockInfo=new DistributedLockInfo();
        lockInfo.setCreateTime(TimeUtils.nowDate());
        lockInfo.setLockKey(lockKey);
        lockInfo.setLockHold(lockHold);
        lockInfo.setLockStatus(DistributedLockStatus.RUN);
        lockInfo.setPeriod(periodSecond);
        lockInfo.setLockExpire(TimeUtils.ofDate(TimeUtils.nowLocalDateTime().plusSeconds(periodSecond)));

        DistributedLock distributedLock=convert(lockInfo);
        if(lockInfo.isPeriodLock()){
            try {
                distributedLockService.insertPeriodLockInfo(distributedLock);
            } catch (Exception e) {
                //log.debug(e.getMessage(), e);
                lockInfo = null;
            }
        }else {
            try {
                distributedLockService.insertLockInfo(distributedLock);
            } catch (Exception e) {
                //log.debug(e.getMessage(), e);
                lockInfo = null;
            }
        }

        return lockInfo;
    }

    @Override
    public void unLock(DistributedLockInfo distributedLockInfo) {
        if(distributedLockInfo.isPeriodLock()){
            //周期分布式锁
            switch (distributedLockInfo.getLockStatus()){
                case FAIL:
                    distributedLockService.delete(distributedLockInfo.getLockKey());
                    break;
                case SUCCESS:
                    distributedLockService.updateStatus(distributedLockInfo.getLockKey(),distributedLockInfo.getLockStatus().name());
                    break;
                case RUN:
                    log.warn("释放锁前锁状态未设置，{}",distributedLockInfo);
                    break;
                default:
                    break;
            }
        }else {
            //非周期分布式锁
            distributedLockService.delete(distributedLockInfo.getLockKey());
        }
    }


    private DistributedLock convert(DistributedLockInfo lockInfo){
        DistributedLock distributedLock=new DistributedLock();
        distributedLock.setLockKey(lockInfo.getLockKey());
        distributedLock.setCreateTime(lockInfo.getCreateTime());
        distributedLock.setLockHold(lockInfo.getLockHold());
        distributedLock.setLockStatus(lockInfo.getLockStatus().name());
        distributedLock.setLockPeriod(lockInfo.getPeriod());
        distributedLock.setLockExpire(lockInfo.getLockExpire());
        return distributedLock;
    }
}
